package com.shop.admin.service.user;


import com.shop.admin.dao.user.StatUserChiefDao;
import com.shop.admin.dao.user.UserDao;
import com.shop.admin.dao.user.UserLevelDao;
import com.shop.admin.dao.user.UserPinkInfoDao;
import com.shop.admin.service.system.SystemService;
import com.shop.admin.service.system.SystemUserLevelService;
import com.shop.admin.dao.pink.*;
import com.shop.common.enums.System.NewSystemConfigEnum;
import com.shop.common.enums.TrueFalseEnum;
import com.shop.common.enums.pink.StorePinkRebateStatusEnum;
import com.shop.common.enums.user.BillTableNameEnum;
import com.shop.common.enums.user.IncomeTypeEnum;
import com.shop.common.enums.user.UserLevelEnum;
import com.shop.domain.pink.*;
import com.shop.domain.system.NewSystemConfig;
import com.shop.domain.system.SystemUserLevel;
import com.shop.domain.user.User;
import com.shop.domain.user.UserLevel;
import com.shop.util.DateUtil;
import com.shop.util.DecimalUtil;
import com.shop.util.StrMaskUtil;
import com.shop.web.exception.GCRuntimeException;
import com.shop.web.response.BaseResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
@Transactional
public class UserService {

    @Autowired
    private UserDao userDao;
    @Autowired
    private StorePinkDao storePinkDao;
    @Autowired
    private UserPinkBillService userPinkBillService;
    @Autowired
    private SystemUserLevelService systemUserLevelService;
    @Autowired
    private AutoPinkDao autoPinkDao;
    @Autowired
    private UserLevelDao userLevelDao;
    @Autowired
    private StatUserChiefDao statUserChiefDao;
    @Autowired
    private StorePinkConfigDao storePinkConfigDao;
    @Autowired
    private SleepPinkBillService sleepPinkBillService;
    @Autowired
    private UserPinkInfoDao userPinkInfoDao;
    @Autowired
    private SystemService systemService;
    @Autowired
    private UserIntegtralBillService userIntegtralBillService;
    @Autowired
    private StoreSnapPinkConfigDao storeSnapPinkConfigDao;
    @Autowired
    private StoreSnapPinkDao storeSnapPinkDao;
    @Autowired
    private SnapRedPinkDao snapRedPinkDao;

    /**
     * 拼团返佣结算
     * @return
     */
    public BaseResponse pinkSettlement(int limit) {


        //返佣错开拼团时间
        StorePinkConfig storePinkConfig = storePinkConfigDao.findSingle(1l);
        if(DateUtil.isEffectiveDate(DateUtil.parseTime(DateUtil.formatTime(new Date())),DateUtil.parseTime(storePinkConfig.getStartTime()),DateUtil.parseTime(storePinkConfig.getEndTime()))){
            return new BaseResponse();
        }

        List<StorePink> pinkList = storePinkDao.findNeedSettlement(limit);
        if(pinkList.size() <= 0) {
            return new BaseResponse();
        }

        log.info("--- 本次需结算的记录共计{}条 ---", pinkList.size());

        long start = System.currentTimeMillis();

        Map<Long, SystemUserLevel> levelMap = systemUserLevelService.levelMap();
        for (StorePink storePink : pinkList) {
            this.pinkSettlement(storePink, levelMap);
        }

        long end = System.currentTimeMillis();

        log.info("--- 本次结算消耗时间共计{}ms ---", (end - start));

        return new BaseResponse();
    }


    /**
     * 拼团返佣结算
     * @return
     */
    public BaseResponse pinkSettlement(StorePink pink, Map<Long, SystemUserLevel> levelMap) {
        // 获取订单用户信息、推荐人信息
        User user = userDao.findSingle(pink.getUid());
        if(null == user) {
            log.error("拼团返佣结算时，用户信息为空！拼团订单id -> {}, 用户id -> {}", pink.getId(), pink.getUid());
            return new BaseResponse();
        }

        // 订单状态
        if(StorePinkRebateStatusEnum.INIT.getKey() != pink.getRebateStatus()) {
            return BaseResponse.fail("该拼团订单非待结算状态！");
        }

        // 获取用户推荐关系
        String spreadids = user.getSpreadids();
        if(StringUtils.isBlank(spreadids)) {
            return new BaseResponse();
        }
        String[] pidArr = spreadids.split(",");

        // 遍历推荐人结算
        Long puid = null;
        User pu = null;
        Long currentLevel = 0L;
        Long lastLevel = 0L;
        SystemUserLevel levelInfo = null;
        BigDecimal profit = null;                   // 实际返佣金额
        BigDecimal levelProfit = null;              // 当前级别的返佣金额
        BigDecimal lastProfit = BigDecimal.ZERO;    // 上一个级别返佣金额
        BigDecimal refreshPrice = null;
        for (String pidStr : pidArr) {
            // 推荐人
            puid = Long.valueOf(pidStr);
            pu = userDao.findSingle(puid);
            if(null == pu) continue;

            // 角色比较
            currentLevel = pu.getLevel();
            if(lastLevel.compareTo(currentLevel) >= 0) {
                continue;
            }

            // 当前角色应获得返佣配置
            levelInfo = levelMap.get(currentLevel);
            if(null == levelInfo) {
                log.error("当前返佣级别未获取到信息！等级id -> {}", currentLevel);
                continue;
            }

            // 佣金计算
            levelProfit = DecimalUtil.percentRate(pink.getTotalAmount().multiply(new BigDecimal(levelInfo.getTeamProportion())));
            // 实际返佣金额 = 当前级别返佣金额 - 上一级别返佣金额
            profit = levelProfit.subtract(lastProfit);
            if(BigDecimal.ZERO.compareTo(profit) < 0) { // 有级差分润
                lastProfit = levelProfit;
            }

            // 结算比例小于等于0
            if(BigDecimal.ZERO.compareTo(profit) >= 0) {
                continue;
            }

     /*       //休眠团长  只增加休眠记录流水
            if(TrueFalseEnum.TRUE.getCode() == pu.getIsSleep()){
                sleepPinkBillService.addUserPinkBill(puid, pink.getId(),pink.getPinkId(),profit,
                        BillTableNameEnum.TEAM_BACK.getKey(), IncomeTypeEnum.INCOME.getKey(), "拼团返佣入账");
            }else{
                // 返佣明细记录
                refreshPrice = pu.getBrokerage().add(profit);
                userPinkBillService.addUserPinkBill(puid, pink.getId(),pink.getPinkId(), pu.getBrokerage(), profit, refreshPrice,
                        BillTableNameEnum.TEAM_BACK.getKey(), IncomeTypeEnum.INCOME.getKey(), "拼团返佣入账");

                // 返佣入账
                userDao.addBrokerage(puid, profit);
            }
*/


            // 更新结算到的角色等级
            lastLevel = currentLevel;
        }

        // 修改订单返佣状态为已完成
        int rebateUpdateRows = storePinkDao.updateRebateStatus(pink.getId(), StorePinkRebateStatusEnum.FINISH.getKey(), StorePinkRebateStatusEnum.INIT.getKey());
        if(rebateUpdateRows <= 0) {
            log.error("拼团订单返佣修改订单状态时，订单状态异常！拼团订单id -> {}", pink.getId());
            throw new GCRuntimeException("10001", "拼团订单返佣修改订单状态时，订单状态异常！");
        }


        return new BaseResponse();
    }


    /**
     * 用户等级升级
     * @return
     */
    public BaseResponse userLevelUpgrade(int limit){

        //返佣错开拼团时间
        StorePinkConfig storePinkConfig = storePinkConfigDao.findSingle(1l);
        if(DateUtil.isEffectiveDate(DateUtil.parseTime(DateUtil.formatTime(new Date())),DateUtil.parseTime(storePinkConfig.getStartTime()),DateUtil.parseTime(storePinkConfig.getEndTime()))){
            return new BaseResponse();
        }

        //查询需要返佣的订单信息
        List<AutoPink> autoPinkList = autoPinkDao.findNeedGradeLevel(limit);

        if(autoPinkList.size() <= 0) {
            return new BaseResponse();
        }

        log.info("--- 本次计算用户升级订单数共计{}条 ---", autoPinkList.size());

        long start = System.currentTimeMillis();

        for (AutoPink autoPink:autoPinkList) {

            this.doUserLevelUpgrade(autoPink);

        }

        long end = System.currentTimeMillis();

        log.info("--- 本次计算用户升级订单数消耗时间共计{}ms ---", (end - start));

        return new BaseResponse();

    }


    //通过订单处理单个用户及推荐人升级
    public BaseResponse doUserLevelUpgrade(AutoPink autoPink){

        User user = userDao.findSingle(autoPink.getUid());
        if(null == user) {
            log.error("用户等级升级计算时候，用户信息为空！续拼（AutoPink）订单id -> {}, 用户id -> {}", autoPink.getId(), autoPink.getUid());
            return new BaseResponse();
        }

        String spreadids = user.getSpreadids();
        if(StringUtils.isBlank(spreadids)) {
            return new BaseResponse();
        }
        String[] pidArr = spreadids.split(",");

        Long puid = null;
        User pu = null;
        boolean notNeedRefresh = true;
        int chiefNum = 0;

        for (String pidStr : pidArr) {
            // 推荐人
            puid = Long.valueOf(pidStr);
            pu = userDao.findSingle(puid);
            if (null == pu) continue;

            //粉丝升级团长 五个粉丝
            if(pu.getLevel() == UserLevelEnum.FANS.getKey()){

                //查询直推粉丝数量
                chiefNum = userDao.queryAllCountFansBySpreadUid(pu.getId());
                notNeedRefresh = this.AddUserLevel(pu,UserLevelEnum.CHIEF,chiefNum);
            }

            //直推用户未从粉丝升级为团长 整条线用户不做等级更新
            if(notNeedRefresh){
                break;
            }

            if(pu.getLevel() == UserLevelEnum.CHIEF.getKey()) { //团长升级l1  直推五个团长

                chiefNum = userDao.queryAllCountL1BySpreadUid(pu.getId());
                this.AddUserLevel(pu,UserLevelEnum.CHIEF,chiefNum);

            }else if(pu.getLevel() == UserLevelEnum.L1.getKey()){//L1 升级L2

                chiefNum = userDao.queryAllCountL1ToL5(pu.getId());
                this.AddUserLevel(pu,UserLevelEnum.L2,chiefNum);

            }else if(pu.getLevel() == UserLevelEnum.L2.getKey()){  //L2升级L3

                chiefNum = userDao.queryAllCountL1ToL5(pu.getId());
                this.AddUserLevel(pu,UserLevelEnum.L3,chiefNum);

            }else if(pu.getLevel() == UserLevelEnum.L3.getKey()){  //L3升级L4

                chiefNum = userDao.queryAllCountL1ToL5(pu.getId());
                this.AddUserLevel(pu,UserLevelEnum.L4,chiefNum);

            }else if(pu.getLevel() == UserLevelEnum.L4.getKey()){  //L4升级L5

                chiefNum = userDao.queryAllCountL1ToL5(pu.getId());
                this.AddUserLevel(pu,UserLevelEnum.L5,chiefNum);

            }else if(pu.getLevel() == UserLevelEnum.L5.getKey()){  //L5升级L6

                chiefNum = userDao.queryAllCountL1ToL5(pu.getId());
                this.AddUserLevel(pu,UserLevelEnum.L6,chiefNum);

            }else if(pu.getLevel() == UserLevelEnum.L6.getKey()){  //l6 升级总裁

                chiefNum = statUserChiefDao.queryShiefNumByUid(pu.getId());
                this.AddUserLevel(pu,UserLevelEnum.CEO,chiefNum);

            }else{  //总裁 等级不需要升级
                continue;
            }

        }

        //新用户首次拼中返积分
        UserPinkInfo userPinkInfo = userPinkInfoDao.findByPinkIdAndUserId(user.getId(),autoPink.getPinkId());
        if(null == userPinkInfo) {
            log.error("用户积分计算时候，用户拼团信息为空！续拼（AutoPink）订单id -> {}, 用户id -> {}", autoPink.getId(), autoPink.getUid());
            return new BaseResponse();
        }
        if(userPinkInfo.getAllPzNum() == 1){ //拼中次数为1 未计算升级  则为新用户拼团第一单
           /* //当前用户获得积分
            NewSystemConfig nowUserSend = systemService.getSystemConfig(NewSystemConfigEnum.RECOMMEND_MEMBER_SEND_INTEGRAL);

            BigDecimal nowUserSendIntegral = new BigDecimal(nowUserSend.getValue());
            BigDecimal nowUserRefreshIntegral = user.getIntegral().add(nowUserSendIntegral);

            userDao.addIntegral(user.getId(), nowUserSendIntegral);
            userIntegtralBillService.addUserIntegralBill(user.getId(), autoPink.getId(), user.getIntegral(),nowUserSendIntegral,nowUserRefreshIntegral,
                    BillTableNameEnum.INTEGRAL_FIRST_PINK_ORDER.getKey(),IncomeTypeEnum.INCOME.getKey(),  "新用户拼团首单，获得积分" + nowUserSendIntegral);
*/

            //推荐人获得积分
            User spreadUser = userDao.findSingle(user.getSpreadUid());
            if(null != spreadUser){
                NewSystemConfig spredUserSend = systemService.getSystemConfig(NewSystemConfigEnum.PINK_SUCCESS_SEND_INGEGRAL);

                BigDecimal spredUserSendIntegral = new BigDecimal(spredUserSend.getValue());
                BigDecimal spredUserRefreshIntegral = spreadUser.getIntegral().add(spredUserSendIntegral);

                userDao.addIntegral(spreadUser.getId(), spredUserSendIntegral);
                userIntegtralBillService.addUserIntegralBill(spreadUser.getId(), autoPink.getId(), spreadUser.getIntegral(),spredUserSendIntegral,spredUserRefreshIntegral,
                        BillTableNameEnum.INTEGRAL_FIRST_PINK_SPREAD_ORDER.getKey(),IncomeTypeEnum.INCOME.getKey(),  "新用户拼团首单，推荐人获得积分" + spredUserSendIntegral);

            }

        }
        //标记订单已处理 升级
        autoPinkDao.updateUserLevelAutoPink(autoPink.getId());


        return new BaseResponse();
    }


    /**
     * 判断用户推荐人数是否达到升级条件
     * @param user
     * @param userLevelEnum
     * @param chiefNum
     * @return
     */
    public boolean AddUserLevel(User user,UserLevelEnum userLevelEnum,int chiefNum){

        //推荐人数达成任务人数
        if(chiefNum >= userLevelEnum.getNum()){


            UserLevel userLevel = new UserLevel();
            userLevel.setUid(user.getId());
            userLevel.setLevelId(user.getLevel());
            userLevel.setGrade(userLevelEnum.getKey());
            userLevel.setMark("尊敬的用户"+StrMaskUtil.maskMobile(user.getAccount())+"在"+DateUtil.getTodayDatetime()+"成为了"+userLevelEnum.getName());
            userLevel.setCreateTime(new Date());
            userLevelDao.save(userLevel);

            userDao.updateUserLevel(user.getId(),Long.parseLong(userLevelEnum.getKey()+""));
            return false;
        }else{
            return true;
        }

    }


    /**
     * 拼团返佣结算
     * @return
     */
    public BaseResponse pinkSnapSettlement(int limit) {


        //返佣错开拼团时间
        StoreSnapPinkConfig storePinkConfig = storeSnapPinkConfigDao.findSingle(2l);
        if(DateUtil.isEffectiveDate(DateUtil.parseTime(DateUtil.formatTime(new Date())),DateUtil.parseTime(storePinkConfig.getStartTime()),DateUtil.parseTime(storePinkConfig.getEndTime()))){
            return new BaseResponse();
        }

        List<SnapRedPink> pinkList = snapRedPinkDao.findNeedSettlement(limit);
        if(pinkList.size() <= 0) {
            return new BaseResponse();
        }

        log.info("--- 本次需结算的记录共计{}条 ---", pinkList.size());

        long start = System.currentTimeMillis();

        Map<Long, SystemUserLevel> levelMap = systemUserLevelService.levelMap();
        for (SnapRedPink storePink : pinkList) {
            this.pinkSnapSettlement(storePink, levelMap);
        }

        long end = System.currentTimeMillis();

        log.info("--- 本次结算消耗时间共计{}ms ---", (end - start));

        return new BaseResponse();
    }


    /**
     * 拼团返佣结算
     * @return
     */
    public BaseResponse pinkSnapSettlement(SnapRedPink pink, Map<Long, SystemUserLevel> levelMap) {
        // 获取订单用户信息、推荐人信息
        User user = userDao.findSingle(pink.getUid());
        if(null == user) {
            log.error("拼团返佣结算时，用户信息为空！拼团订单id -> {}, 用户id -> {}", pink.getId(), pink.getUid());
            return new BaseResponse();
        }

        // 获取用户推荐关系
        String spreadids = user.getSpreadids();
        if(StringUtils.isBlank(spreadids)) {
            return new BaseResponse();
        }
        String[] pidArr = spreadids.split(",");

        // 遍历推荐人结算
        Long puid = null;
        User pu = null;
        Long currentLevel = 0L;
        Long lastLevel = 0L;
        SystemUserLevel levelInfo = null;
        BigDecimal profit = null;                   // 实际返佣金额
        BigDecimal levelProfit = null;              // 当前级别的返佣金额
        BigDecimal lastProfit = BigDecimal.ZERO;    // 上一个级别返佣金额
        BigDecimal refreshPrice = null;
        for (String pidStr : pidArr) {
            // 推荐人
            puid = Long.valueOf(pidStr);
            pu = userDao.findSingle(puid);
            if(null == pu) continue;

            // 角色比较
            currentLevel = pu.getLevel();
            if(lastLevel.compareTo(currentLevel) >= 0) {
                continue;
            }

            // 当前角色应获得返佣配置
            levelInfo = levelMap.get(currentLevel);
            if(null == levelInfo) {
                log.error("当前返佣级别未获取到信息！等级id -> {}", currentLevel);
                continue;
            }

            // 佣金计算
            levelProfit = DecimalUtil.percentRate(pink.getRedAmount().multiply(new BigDecimal(levelInfo.getTeamProportion())));
            // 实际返佣金额 = 当前级别返佣金额 - 上一级别返佣金额
            profit = levelProfit.subtract(lastProfit);
            if(BigDecimal.ZERO.compareTo(profit) < 0) { // 有级差分润
                lastProfit = levelProfit;
            }

            // 结算比例小于等于0
            if(BigDecimal.ZERO.compareTo(profit) >= 0) {
                continue;
            }

       /*     //休眠团长  只增加休眠记录流水
            if(TrueFalseEnum.TRUE.getCode() == pu.getIsSleep()){
                sleepPinkBillService.addUserPinkBill(puid, pink.getId(),pink.getPinkId(),profit,
                        BillTableNameEnum.TEAM_BACK.getKey(), IncomeTypeEnum.INCOME.getKey(), "抢购拼团返佣入账");
            }else{
                // 返佣明细记录
                refreshPrice = pu.getBrokerage().add(profit);
                userPinkBillService.addUserPinkBill(puid, pink.getId(),pink.getPinkId(), pu.getBrokerage(), profit, refreshPrice,
                        BillTableNameEnum.TEAM_BACK.getKey(), IncomeTypeEnum.INCOME.getKey(), "抢购拼团返佣入账");

                // 返佣入账
                userDao.addBrokerage(puid, profit);
            }*/



            // 更新结算到的角色等级
            lastLevel = currentLevel;
        }

        // 修改订单返佣状态为已完成
        int rebateUpdateRows = storePinkDao.updateRebateStatus(pink.getId(), StorePinkRebateStatusEnum.FINISH.getKey(), StorePinkRebateStatusEnum.INIT.getKey());
        if(rebateUpdateRows <= 0) {
            log.error("拼团订单返佣修改订单状态时，订单状态异常！拼团订单id -> {}", pink.getId());
            throw new GCRuntimeException("10001", "拼团订单返佣修改订单状态时，订单状态异常！");
        }


        return new BaseResponse();
    }


}
